package cn.iocoder.boot.springai001.controller;

import cn.iocoder.boot.springai001.provider.DynamicMcpToolProvider;
import cn.iocoder.boot.springai001.service.ChatService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

import java.util.Set;

/**
 * 基于场景的对话控制器
 * <p>
 * 展示如何使用DynamicMcpToolProvider实现不同场景下的工具隔离
 * <p>
 * API路径示例：
 * - /api/v1/chat/scenario/file - 文件管理场景，只能使用filesystem工具
 * - /api/v1/chat/scenario/web - 网络访问场景，只能使用fetch工具
 * - /api/v1/chat/scenario/data - 数据分析场景，可以使用excel和fetch工具
 * - /api/v1/chat/scenario/role - 基于角色的权限控制
 */
@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/api/v1/chat/scenario")
@Tag(name = "场景化对话", description = "根据不同场景提供定制化的AI对话能力")
public class ScenarioBasedChatController {

    @Resource
    private DynamicMcpToolProvider toolProvider;

    @Resource
    private ChatService chatService;

    /**
     * 文件管理场景
     * 只允许访问文件系统相关工具
     */
    @Operation(
            summary = "文件管理对话",
            description = "只能使用文件系统工具的受限对话，适用于文件读写、目录管理等场景"
    )
    @GetMapping(value = "/file", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ChatResponse> fileManagementChat(
            @Parameter(description = "用户问题，如：读取某个文件、列出目录等")
            @RequestParam String query,
            @Parameter(description = "会话ID")
            @RequestParam(defaultValue = "file-session") String uid) {

        log.info("【文件管理场景】会话ID: {}, 问题: {}", uid, query);

        // 只允许使用filesystem工具
        ToolCallbackProvider provider = toolProvider.buildProvider(Set.of("filesystem"));

        return chatService.chatWithTools(
                provider,
                query,
                "你是一个文件管理助手，可以帮助用户进行文件操作。",
                null,  // 不支持图片
                "gpt-4o",
                0.7,
                uid
        );
    }

    /**
     * 网络访问场景
     * 只允许访问网络请求工具
     */
    @Operation(
            summary = "网络访问对话",
            description = "只能使用fetch工具的对话，适用于获取网页内容、API调用等场景"
    )
    @GetMapping(value = "/web", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ChatResponse> webAccessChat(
            @Parameter(description = "用户问题，如：获取网页内容、调用API等")
            @RequestParam String query,
            @Parameter(description = "会话ID")
            @RequestParam(defaultValue = "web-session") String uid) {

        log.info("【网络访问场景】会话ID: {}, 问题: {}", uid, query);

        // 只允许使用fetch工具
        ToolCallbackProvider provider = toolProvider.buildProvider(Set.of("fetch"));

        return chatService.chatWithTools(
                provider,
                query,
                "你是一个网络助手，可以帮助用户获取网络资源和调用API。",
                null,
                "gpt-4o",
                0.7,
                uid
        );
    }

    /**
     * 数据分析场景
     * 允许访问Excel和网络工具
     */
    @Operation(
            summary = "数据分析对话",
            description = "可以使用Excel和fetch工具的对话，适用于数据处理、分析等场景"
    )
    @GetMapping(value = "/data", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ChatResponse> dataAnalysisChat(
            @Parameter(description = "用户问题，如：分析Excel数据、从网络获取数据并分析等")
            @RequestParam String query,
            @Parameter(description = "会话ID")
            @RequestParam(defaultValue = "data-session") String uid) {

        log.info("【数据分析场景】会话ID: {}, 问题: {}", uid, query);

        // 允许使用excel和fetch工具
        ToolCallbackProvider provider = toolProvider.buildProvider(Set.of("excel", "fetch"));

        return chatService.chatWithTools(
                provider,
                query,
                "你是一个数据分析助手，可以处理Excel文件和从网络获取数据。",
                null,
                "gpt-4o",
                0.7,
                uid
        );
    }

    /**
     * 基于角色的对话
     * 根据用户角色动态选择工具集
     */
    @Operation(
            summary = "基于角色的对话",
            description = "根据用户角色（admin/developer/readonly）提供不同的工具访问权限"
    )
    @GetMapping(value = "/role", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ChatResponse> roleBasedChat(
            @Parameter(description = "用户问题")
            @RequestParam String query,
            @Parameter(description = "用户角色：admin（全部权限）、developer（fetch+excel）、readonly（仅fetch）")
            @RequestParam(defaultValue = "readonly") String role,
            @Parameter(description = "会话ID")
            @RequestParam(defaultValue = "role-session") String uid) {

        log.info("【角色对话场景】角色: {}, 会话ID: {}, 问题: {}", role, uid, query);

        // 根据角色选择工具
        ToolCallbackProvider provider = toolProvider.getProviderByRole(role);

        String systemPrompt = switch (role.toLowerCase()) {
            case "admin" -> "你是管理员助手，拥有完整的系统访问权限。";
            case "developer" -> "你是开发者助手，可以访问网络和Excel工具。";
            case "readonly" -> "你是只读助手，只能获取网络资源。";
            default -> "你是一个AI助手。";
        };

        return chatService.chatWithTools(
                provider,
                query,
                systemPrompt,
                null,
                "gpt-4o",
                0.7,
                uid
        );
    }

    /**
     * 自定义场景对话
     * 允许用户自定义选择哪些MCP服务器
     */
    @Operation(
            summary = "自定义场景对话",
            description = "允许自定义选择MCP服务器，多个服务器用逗号分隔"
    )
    @GetMapping(value = "/custom", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ChatResponse> customScenarioChat(
            @Parameter(description = "用户问题")
            @RequestParam String query,
            @Parameter(description = "允许的服务器列表，逗号分隔，如：filesystem,fetch")
            @RequestParam String servers,
            @Parameter(description = "会话ID")
            @RequestParam(defaultValue = "custom-session") String uid) {

        if (!StringUtils.hasText(servers)) {
            log.warn("未指定服务器列表，使用所有服务器");
            servers = "filesystem,fetch,excel,everything";
        }

        Set<String> serverSet = Set.of(servers.split(","));
        log.info("【自定义场景】服务器: {}, 会话ID: {}, 问题: {}", serverSet, uid, query);

        // 按指定的服务器列表选择工具
        ToolCallbackProvider provider = toolProvider.buildProvider(serverSet);

        return chatService.chatWithTools(
                provider,
                query,
                "你是一个灵活的AI助手，可以使用多种工具帮助用户。",
                null,
                "gpt-4o",
                0.7,
                uid
        );
    }

    /**
     * 获取场景信息
     * 返回各个场景可用的工具列表
     */
    @Operation(
            summary = "获取场景信息",
            description = "查询各个预定义场景可以使用的工具"
    )
    @GetMapping("/info")
    public java.util.Map<String, Object> getScenarioInfo() {
        log.info("查询场景信息");

        return java.util.Map.of(
                "scenarios", java.util.List.of(
                        java.util.Map.of(
                                "name", "file",
                                "description", "文件管理场景",
                                "servers", java.util.List.of("filesystem"),
                                "endpoint", "/api/v1/chat/scenario/file"
                        ),
                        java.util.Map.of(
                                "name", "web",
                                "description", "网络访问场景",
                                "servers", java.util.List.of("fetch"),
                                "endpoint", "/api/v1/chat/scenario/web"
                        ),
                        java.util.Map.of(
                                "name", "data",
                                "description", "数据分析场景",
                                "servers", java.util.List.of("excel", "fetch"),
                                "endpoint", "/api/v1/chat/scenario/data"
                        )
                ),
                "roles", java.util.Map.of(
                        "admin", java.util.List.of("filesystem", "fetch", "excel", "everything"),
                        "developer", java.util.List.of("fetch", "excel"),
                        "readonly", java.util.List.of("fetch")
                ),
                "availableServers", toolProvider.getAvailableServerNames()
        );
    }
}

